<?php
/**
 * Created by PhpStorm.
 * User: 图图
 * Date: 2021-6-11
 * Time: 11:04
 */
namespace app\common\controller;

use think\Controller;
use think\facade\Env;
use unionpay\AcpService as AcpServiceModel;
use unionpay\SDKConfig;
use function unionpay\argSort;
use function unionpay\createLinkString;

class Unionpay extends Controller
{

    public function get_tn($order_no,$money,$backUrl='')
    {

        //dump($order_no);die;
        $params = array(
            //以下信息非特殊情况不需要改动
            'version' => SDKConfig::getSDKConfig()->version,                 //版本号
            'encoding' => 'utf-8',				  //编码方式
            'txnType' => '01',				      //交易类型
            'txnSubType' => '01',				  //交易子类
            'bizType' => '000201',				  //业务类型
            'frontUrl' =>  SDKConfig::getSDKConfig()->frontUrl,  //前台通知地址
            'backUrl' =>$backUrl==''?SDKConfig::getSDKConfig()->backUrl:$backUrl,	  //后台通知地址
            'signMethod' => SDKConfig::getSDKConfig()->signMethod,	              //签名方法
            'channelType' => '08',	              //渠道类型，07-PC，08-手机
            'accessType' => '0',		          //接入类型
            'currencyCode' => '156',	          //交易币种，境内商户固定156

            //TODO 以下信息需要填写
            'merId' => '777290058110048',		//商户代码，请改自己的测试商户号，此处默认取demo演示页面传递的参数
            'orderId' => $order_no,	//商户订单号，8-32位数字字母，不能含“-”或“_”，此处默认取demo演示页面传递的参数，可以自行定制规则
            'txnTime' => date('Ymdhis'),	//订单发送时间，格式为YYYYMMDDhhmmss，取北京时间，此处默认取demo演示页面传递的参数
            'txnAmt' => $money	//交易金额，单位分，此处默认取demo演示页面传递的参数

            // 请求方保留域，
            // 透传字段，查询、通知、对账文件中均会原样出现，如有需要请启用并修改自己希望透传的数据。
            // 出现部分特殊字符时可能影响解析，请按下面建议的方式填写：
            // 1. 如果能确定内容不会出现&={}[]"'等符号时，可以直接填写数据，建议的方法如下。
            //    'reqReserved' =>'透传信息1|透传信息2|透传信息3',
            // 2. 内容可能出现&={}[]"'符号时：
            // 1) 如果需要对账文件里能显示，可将字符替换成全角＆＝｛｝【】“‘字符（自己写代码，此处不演示）；
            // 2) 如果对账文件没有显示要求，可做一下base64（如下）。
            //    注意控制数据长度，实际传输的数据长度不能超过1024位。
            //    查询、通知等接口解析时使用base64_decode解base64后再对数据做后续解析。
            //    'reqReserved' => base64_encode('任意格式的信息都可以'),

            //TODO 其他特殊用法请查看 pages/api_05_app/special_use_purchase.php
        );
        //dump($params);die;
        AcpServiceModel::sign ( $params ); // 签名
        $url = SDKConfig::getSDKConfig()->appTransUrl;
        $result_arr = AcpServiceModel::post ($params,$url);
        if(count($result_arr)<=0) { //没收到200应答的情况
            $this->printResult ($url, $params, "" );
            return;
        }

        $this->printResult ($url, $params, $result_arr ); //页面打印请求应答数据
        if (!AcpServiceModel::validate ($result_arr) ){
            echo "应答报文验签失败<br>\n";
            return;
        }


        echo "应答报文验签成功<br>\n";
        if ($result_arr["respCode"] == "00"){
            //成功
            //TODO
            echo "成功接收tn：" . $result_arr["tn"] . "<br>\n";
            echo "后续请将此tn传给手机开发，由他们用此tn调起控件后完成支付。<br>\n";
            echo "手机端demo默认从仿真获取tn，仿真只返回一个tn，如不想修改手机和后台间的通讯方式，【此页面请修改代码为只输出tn】。<br>\n";
        } else {
            //其他应答码做以失败处理
            //TODO
            echo "失败：" . $result_arr["respMsg"] . "。<br>\n";
        }
    }
    /**
     * 打印请求应答
     *
     * @param
     *        	$url
     * @param
     *        	$req
     * @param
     *        	$resp
     */
    function printResult($url, $req, $resp) {
        echo "=============<br>\n";
        echo "地址：" . $url . "<br>\n";
        echo "请求：" . str_replace ( "\n", "\n<br>", htmlentities ( createLinkString ( $req, false, true ) ) ) . "<br>\n";
        echo "应答：" . str_replace ( "\n", "\n<br>", htmlentities ( createLinkString ( $resp , false, false )) ) . "<br>\n";
        echo "=============<br>\n";
    }
    //验签
    public function notify($arr)
    {
        try{
            $data = AcpServiceModel::validate ( $arr );
            if($data){
                return  true;
            }
        } catch (\Exception $e) {
            return  false;
        }
    }

    /**
     * @param $orderId 退款单号
     * @param $money 退款金额
     * @param $origQryId 原订单标识
     */
    public  function refund($orderId,$money,$origQryId){

        $params = array(

            //以下信息非特殊情况不需要改动
            'version' => SDKConfig::getSDKConfig()->version,		      //版本号
            'encoding' => 'utf-8',		      //编码方式
            'signMethod' => SDKConfig::getSDKConfig()->signMethod,		      //签名方法
            'txnType' => '04',		          //交易类型
            'txnSubType' => '00',		      //交易子类
            'bizType' => '000201',		      //业务类型
            'accessType' => '0',		      //接入类型
            'channelType' => '07',		      //渠道类型
            'backUrl' => SDKConfig::getSDKConfig()->backUrl, //后台通知地址

            //TODO 以下信息需要填写
            'orderId' =>$orderId,	    //商户订单号，8-32位数字字母，不能含“-”或“_”，可以自行定制规则，重新产生，不同于原消费，此处默认取demo演示页面传递的参数
            'merId' =>'777290058110048',	        //商户代码，请改成自己的测试商户号，此处默认取demo演示页面传递的参数
            'origQryId' =>$origQryId, //原消费的queryId，可以从查询接口或者通知接口中获取，此处默认取demo演示页面传递的参数
            'txnTime' => date('Ymdhis'),	    //订单发送时间，格式为YYYYMMDDhhmmss，重新产生，不同于原消费，此处默认取demo演示页面传递的参数
            'txnAmt' =>$money,       //交易金额，退货总金额需要小于等于原消费

            // 请求方保留域，
            // 透传字段，查询、通知、对账文件中均会原样出现，如有需要请启用并修改自己希望透传的数据。
            // 出现部分特殊字符时可能影响解析，请按下面建议的方式填写：
            // 1. 如果能确定内容不会出现&={}[]"'等符号时，可以直接填写数据，建议的方法如下。
            //    'reqReserved' =>'透传信息1|透传信息2|透传信息3',
            // 2. 内容可能出现&={}[]"'符号时：
            // 1) 如果需要对账文件里能显示，可将字符替换成全角＆＝｛｝【】“‘字符（自己写代码，此处不演示）；
            // 2) 如果对账文件没有显示要求，可做一下base64（如下）。
            //    注意控制数据长度，实际传输的数据长度不能超过1024位。
            //    查询、通知等接口解析时使用base64_decode解base64后再对数据做后续解析。
            //    'reqReserved' => base64_encode('任意格式的信息都可以'),
        );

        AcpServiceModel::sign ( $params ); // 签名
        $url = SDKConfig::getSDKConfig()->backTransUrl;

        $result_arr = AcpServiceModel::post ( $params, $url);
        if(count($result_arr)<=0) { //没收到200应答的情况
            $this->printResult ( $url, $params, "" );
            return;
        }
        $this->printResult ($url, $params, $result_arr ); //页面打印请求应答数据

        if (!AcpServiceModel::validate ($result_arr) ){
            echo "应答报文验签失败<br>\n";
            return;
        }
        echo "应答报文验签成功<br>\n";
        if ($result_arr["respCode"] == "00"){
            //交易已受理，等待接收后台通知更新订单状态，如果通知长时间未收到也可发起交易状态查询
            //TODO
            echo "受理成功。<br>\n";
        } else if ($result_arr["respCode"] == "03"
            || $result_arr["respCode"] == "04"
            || $result_arr["respCode"] == "05" ){
            //后续需发起交易状态查询交易确定交易状态
            //TODO
            echo "处理超时，请稍微查询。<br>\n";
        } else {
            //其他应答码做以失败处理
            //TODO
            echo "失败：" . $result_arr["respMsg"] . "。<br>\n";
        }
    }


}
